#pragma once

#include <linux/types.h>
#include <linux/rbtree_types.h>

struct sched_dl_entity;

struct sched_rt_entity
{
    struct list_head run_list;
    unsigned long timeout;
    struct sched_rt_entity *back;
    short prio;
    unsigned char on_rq;
    unsigned short on_list;
    unsigned int time_slice;
};

struct load_weight
{
    unsigned long weight;
    unsigned long inv_weight;
};

struct sched_entity
{
    /* For load-balancing: */
    struct load_weight load;
    struct rb_node run_node;
    u64 deadline;
    u64 min_vruntime;
    u64 vruntime;
    u64 slice;
    u64 min_slice;
    u64 exec_start;
    u64 sum_exec_runtime;

    unsigned char sched_delayed;
    unsigned char on_rq;
    unsigned char rel_deadline;
    unsigned char custom_slice;
};

typedef bool (*dl_server_has_tasks_f)(struct sched_dl_entity *);
typedef struct task_struct *(*dl_server_pick_f)(struct sched_dl_entity *);

struct sched_dl_entity
{
    struct rb_node rb_node;
    u64 deadline; /* Absolute deadline for this instance	*/

    /*
     * Some bool flags:
     *
     * @dl_throttled tells if we exhausted the runtime. If so, the
     * task has to wait for a replenishment to be performed at the
     * next firing of dl_timer.
     *
     * @dl_yielded tells if task gave up the CPU before consuming
     * all its available runtime during the last job.
     *
     * @dl_non_contending tells if the task is inactive while still
     * contributing to the active utilization. In other words, it
     * indicates if the inactive timer has been armed and its handler
     * has not been executed yet. This flag is useful to avoid race
     * conditions between the inactive timer handler and the wakeup
     * code.
     *
     * @dl_overrun tells if the task asked to be informed about runtime
     * overruns.
     *
     * @dl_server tells if this is a server entity.
     *
     * @dl_defer tells if this is a deferred or regular server. For
     * now only defer server exists.
     *
     * @dl_defer_armed tells if the deferrable server is waiting
     * for the replenishment timer to activate it.
     *
     * @dl_server_active tells if the dlserver is active(started).
     * dlserver is started on first cfs enqueue on an idle runqueue
     * and is stopped when a dequeue results in 0 cfs tasks on the
     * runqueue. In other words, dlserver is active only when cpu's
     * runqueue has atleast one cfs task.
     *
     * @dl_defer_running tells if the deferrable server is actually
     * running, skipping the defer phase.
     */
    unsigned int dl_throttled : 1;
    unsigned int dl_yielded : 1;
    unsigned int dl_non_contending : 1;
    unsigned int dl_overrun : 1;
    unsigned int dl_server : 1;
    unsigned int dl_server_active : 1;
    unsigned int dl_defer : 1;
    unsigned int dl_defer_armed : 1;
    unsigned int dl_defer_running : 1;

    struct rq *rq;
    dl_server_has_tasks_f server_has_tasks;
    dl_server_pick_f server_pick_task;

    struct sched_dl_entity *pi_se;
};
